/**
 * @file  chip.h
 * @brief  this file is referred from core system
 *
 * @date   2011/05/08
 * @author K.Akasaka
 */

#ifndef CHIP_H_
#define CHIP_H_

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>


/* Interrupt controller */
#define _Enable_Int()        {PMIC.CTRL = PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm; sei();}
#define _Disable_Int()       cli()

/* External SRAM system function/macro*/
#define _EXBUS_read(addr)                            \
        (__extension__({                                \
		unsigned long int temp32 = (unsigned long int)(addr);     \
		unsigned char result;                         \
		asm volatile(                           \
			"in __tmp_reg__, %2"     "\n\t" \
			"out %2, %C1"            "\n\t" \
			"movw r30, %1"           "\n\t" \
			"ld %0, Z"               "\n\t" \
			"out %2, __tmp_reg__"    "\n\t" \
			: "=r" (result)                 \
			: "r" (temp32),                 \
			  "I" (_SFR_IO_ADDR(RAMPZ))     \
			: "r30", "r31"                  \
		);                                      \
		result;                                 \
	}))

#define _EXBUS_write(addr, data)                     \
        (__extension__({                                \
		unsigned long int temp32 = (unsigned long int)(addr);     \
		asm volatile(                           \
			"in __tmp_reg__, %1"     "\n\t" \
			"out %1, %C0"            "\n\t" \
			"movw r30, %0"           "\n\t" \
			"st Z, %2"               "\n\t" \
			"out %1, __tmp_reg__"           \
			:                               \
			: "r" (temp32),                 \
			  "I" (_SFR_IO_ADDR(RAMPZ)),    \
			  "r" ((unsigned char)data)           \
			: "r30", "r31"                  \
		);                                      \
	}))


#define xmega_mem_enter_ISR()  uint8_t volatile saved_rampz = RAMPZ; \
                               RAMPZ = 0;

#define xmega_mem_exit_ISR()   RAMPZ = saved_rampz;



/* for GPIO control */
#define _TGT_current()	(PORTA.IN & 0x7)
#define _TGT0_Lo()      (PORTA.OUTCLR = 0x01)
#define _TGT1_Lo()      (PORTA.OUTCLR = 0x02)
#define _TGT2_Lo()      (PORTA.OUTCLR = 0x04)

#define _TGT0_Hi()      (PORTA.OUTSET = 0x01)
#define _TGT1_Hi()      (PORTA.OUTSET = 0x02)
#define _TGT2_Hi()      (PORTA.OUTSET = 0x04)


#define _GIO0_state()   ((PORTA.IN >> 3) & 0x01)
#define _GIO1_state()   ((PORTA.IN >> 4) & 0x01)
#define _GIO2_state()   ((PORTA.IN >> 6) & 0x01)
#define _GIO3_state()   ((PORTA.IN >> 7) & 0x01)
#define _GIO_OR_state() ((PORTA.IN >> 5) & 0x01)

#define _GIO0_Lo()      (PORTA.OUTCLR = 0x08)
#define _GIO1_Lo()      (PORTA.OUTCLR = 0x10)
#define _GIO2_Lo()      (PORTA.OUTCLR = 0x40)
#define _GIO3_Lo()      (PORTA.OUTCLR = 0x80)
#define _GIO_OR_Lo()    (PORTA.OUTCLR = 0x20)

#define _GIO0_Hi()      (PORTA.OUTSET = 0x08)
#define _GIO1_Hi()      (PORTA.OUTSET = 0x10)
#define _GIO2_Hi()      (PORTA.OUTSET = 0x40)
#define _GIO3_Hi()      (PORTA.OUTSET = 0x80)
#define _GIO_OR_Hi()    (PORTA.OUTSET = 0x20)

#define _GIO0_dir_O()   (PORTA.DIRSET = 0x08)
#define _GIO1_dir_O()   (PORTA.DIRSET = 0x10)
#define _GIO2_dir_O()   (PORTA.DIRSET = 0x40)
#define _GIO3_dir_O()   (PORTA.DIRSET = 0x80)
#define _GIO_OR_dir_O() (PORTA.DIRSET = 0x20)

#define _GIO0_dir_I()   (PORTA.DIRCLR = 0x08)
#define _GIO1_dir_I()   (PORTA.DIRCLR = 0x10)
#define _GIO2_dir_I()   (PORTA.DIRCLR = 0x40)
#define _GIO3_dir_I()   (PORTA.DIRCLR = 0x80)
#define _GIO_OR_dir_I() (PORTA.DIRCLR = 0x20)

/* for Ext Reset Control */
#define _SS_RESET_ASSERT() (PORTB.OUTCLR = 0x08)
#define _SS_RESET_NEGATE() (PORTB.OUTSET = 0x08)

#endif /* CHIP_H_ */
